#ifndef VECTOR3_H
#define VECTOR3_H

class Vector3
{
public:
	union
	{
		struct
		{
			float x, y, z;
		};
		float v[3];
	};

	Vector3() : x(0.0f), y(0.0f), z(0.0f) {};
	Vector3(float x, float y, float z) : x(x), y(y), z(z) {};
	Vector3(const Vector3& v) : x(v.x), y(v.y), z(v.z) {};

	inline void operator =(const Vector3& a)
	{
		x = a.x; y = a.y; z = a.z;	
	}

	inline const Vector3 operator+(const Vector3& a) const
	{
		return Vector3(x+a.x, y+a.y, z+a.z);
	}

	inline Vector3& operator += (const Vector3& in)
	{
		x += in.x; y += in.y; z += in.z;
		return *this; 
	}

	inline const Vector3 operator-(const Vector3& a) const
	{
		return Vector3(x-a.x, y-a.y, z-a.z);
	}

	inline Vector3& operator -= (const Vector3& in)
	{
		x -= in.x; y -= in.y; z -= in.z;
		return *this; 
	}

	inline const Vector3 operator*(const float& a) const
	{	
		return Vector3(x*a, y*a, z*a);
	}

	inline Vector3& operator *= ( const float& in )
	{
		x *= in; y *= in; z *= in;
		return *this;
	}

	inline Vector3& operator /= ( const float& in )
	{
		float inv = 1.0f / in;
		x *= inv;
		y *= inv;
		z *= inv;
		return *this;
	}

	inline const Vector3 operator/(const float&  a) const
	{
		float inv = 1.0f / a;
		return Vector3(x*inv, y*inv, z*inv);
	}

	inline bool operator==(const Vector3& a) const
	{
		return (eql(x, a.x) && eql(y, a.y) && eql(z, a.z));
	}

	inline bool operator!=(const Vector3& a) const
	{
		return !(*this == a);
	}

	inline float length() const
	{
		return sqrt(x*x + y*y + z*z);
	}

	inline void normalize()
	{
		float inv = 1.0f / length();
		x *= inv; y *= inv; z *= inv;
	}

	static inline const float dot(const Vector3& a, const Vector3& b)
	{
		return a.x*b.x + a.y*b.y + a.z*b.z;
	}

	static inline const Vector3 cross(const Vector3& a, const Vector3& b)
	{
		return Vector3( (a.y*b.z-a.z*b.y), (a.z*b.x-a.x*b.z), (a.x*b.y-a.y*b.x) );
	}

	static inline const Vector3 reflect(const Vector3& v, const Vector3& n)
	{
		return (v - (n * Vector3::dot(v, n) * 2.0f));
	}	
};

#endif

